#ifndef CAMERAIMAGE_H
#define CAMERAIMAGE_H

#include <QObject>
#include <QImage>
#include <QSize>
#include <QMutex>
#include <QVideoFrame>
#include <QAbstractVideoSurface>
#include "bayer2rgb.h"
#include "yuv2rgb.h"
#include "bayer2rgb.h"
#include "FocusMeasure.h"

/**
 * @brief The CameraImage class 这个类是纯虚类，提供了相机原始图像数据到 QImage 类的转换功能。
 */
class CameraImage : public QAbstractVideoSurface
{
    Q_OBJECT
public:
    QList<QVideoFrame::PixelFormat> supportedPixelFormats(
            QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const Q_DECL_OVERRIDE;

    enum FlipMode{ NONE = 0, HORIZONTAL_FLIP = 1, VERTICAL_FLIP = 2, BOTH = 3};
    explicit CameraImage(QObject *parent = 0);

    /**
     * @brief getImage 获取图像
     * @return
     */
    QImage getImage();

    /**
    * @brief 加载文件中的图像
    * @param fileName 带路径的完整文件名
    * @return true 表示加载成功，false 表示加载失败
    */
    bool loadImage(const QString &fileName);

    /**
     * @brief saveImage 将图像保存到文件中
     * @param fileName 带路径的完整文件名
     * @return true 表示保存成功
     */
    bool saveImage(const QString &fileName);

    void startFocus();
    void stopFocus();
    QImage getBestImage();
signals:
    /**
     * @brief flipModeChanged 图像翻转模式改变时发送这个信号
     * @param mode
     */
    void flipModeChanged(CameraImage::FlipMode mode);
    /**
     * @brief bayerPatternChanged Color Filter 起始图案更改时发送这个信号
     * @param pattern
     */
    void bayerPatternChanged(BAYER_PATTERN pattern);
    /**
     * @brief bayerMethodChanged Bayer 解码方法变更时发送这个信号
     * @param method
     */
    void bayerMethodChanged(BAYER_METHOD method);
    /**
     * @brief imageChanged 当图像发生变化时发送这个信号
     * @param RGB24Image
     */
    void imageChanged(const QImage &RGB24Image);
public slots:
    void setVideoFrame(const QVideoFrame &frame);
    virtual void setImage(const QImage &image) = 0;
    virtual void setRGB24Image(const uint8_t *imgBuf, QSize size) = 0;
    virtual void setRGB32Image(const uint8_t *imgBuf, QSize size) = 0;
    virtual void setMono8Image(const uint8_t *imgBuf, QSize size) = 0;
    virtual void setYUY2Image(const uint8_t *imgBuf, QSize size) = 0;
    virtual void setVYUYImage(const uint8_t *imgBuf, QSize size) = 0;
    virtual void setUYVYImage(const uint8_t *imgBuf, QSize size) = 0;
    virtual void setBayerImage(const uint8_t *imgBuf, QSize size) = 0;
    virtual void fillImageTestPattern() = 0;
    /**
     * @brief setFlipMode 设置图像翻转的模式。每次更新图像时，可以对图像进行左右翻转或上下翻转，也可同时翻转。
     * @param flipMode
     */
    void setFlipMode(CameraImage::FlipMode flipMode);
    /**
     * @brief setHorizontalFlip 设置图像是否左右翻转
     * @param on true 表示开启图像左右翻转
     */
    void setHorizontalFlip(bool on);
    /**
     * @brief setVerticalFlip 设置图像是否上下翻转
     * @param on true 表示开启图像上下翻转
     */
    void setVerticalFlip(bool on);
    /**
     * @brief setBayerPattern 制定 Color Filter 的起始图案
     * @param pattern
     */
    void setBayerPattern(BAYER_PATTERN pattern);
    /**
     * @brief setBayerMethod 设置 Bayer 格式转为 RGB 的方法
     * @param method
     */
    void setBayerMethod(BAYER_METHOD method);
protected:
    int m_flip_mode; // 这里故意设为int类型，不用FlipMode类型
    BAYER_PATTERN m_bayer_pattern;
    BAYER_METHOD m_bayer_method;
    YUV2RGBConverter m_yuvConverter;
    QImage m_image;
    int m_image_count;
    QMutex m_image_mutex; ///< m_image 会被多个线程访问，需用 mutex 保护

    FocusMeasure m_focusMeasure;
    QImage bestImage;
    bool isFocus;
    double bestScore;
private:
    virtual void flipImage(QImage &image, FlipMode flip_mode) = 0;
private slots:
    bool present(const QVideoFrame &frame) Q_DECL_OVERRIDE;
};

#endif // CAMERAIMAGE_H
